<?php

namespace yifang\lib;

use InvalidArgumentException;
use yifang\utils\Arr;
use yifang\log\ChannelSet;
use yifang\log\Channel;

class Log extends Manager
{
    const EMERGENCY = 'emergency';
    const ALERT     = 'alert';
    const CRITICAL  = 'critical';
    const ERROR     = 'error';
    const WARNING   = 'warning';
    const NOTICE    = 'notice';
    const INFO      = 'info';
    const DEBUG     = 'debug';
    const SQL       = 'sql';

    protected $namespace = '\\yifang\\log\\driver\\';

    /**
     * 默认驱动
     * @return string|null
     */
    public function getDefaultDriver()
    {
        return $this->getConfig('default');
    }

    /**
     * 获取渠道配置
     */
    public function getChannelConfig($channel, $name = null, $default = null)
    {
        if ($config = $this->getConfig("channels.{$channel}")) {
            return Arr::get($config, $name, $default);
        }
        throw new InvalidArgumentException("Channel [$channel] not found.");
    }

    /**
     * driver()的别名
     */
    public function channel($name = null)
    {
        if (is_array($name)) {
            return new ChannelSet($this, $name);
        }
        return $this->driver($name);
    }

    /**
     * 记录日志信息
     */
    public function record($msg, $type = 'info', array $context = [], $lazy = true)
    {
        $channel = $this->getConfig('type_channel.' . $type);
        $this->channel($channel)->record($msg, $type, $context, $lazy);
        return $this;
    }

    /**
     * 获取日志配置
     */
    public function getConfig($name = null, $default = null)
    {
        if (!is_null($name)) {
            return $this->app->config->get('log.' . $name, $default);
        }
        return $this->app->config->get('log');
    }

    /**
     * 解析类型
     */
    protected function resolveType($name)
    {
        return $this->getChannelConfig($name, 'type', 'file');
    }

    /**
     * 创建驱动
     * @param $name
     * @return Channel
     */
    public function createDriver($name)
    {
        $driver = parent::createDriver($name);
        $lazy  = !$this->getChannelConfig($name, "realtime_write", false) && !$this->app->runningInConsole();
        $allow = array_merge($this->getConfig("level", []), $this->getChannelConfig($name, "level", []));
        return new Channel($name, $driver, $allow, $lazy, $this->app->event);
    }

    protected function resolveConfig($name)
    {
        return $this->getChannelConfig($name);
    }

    /**
     * 清空日志信息
     */
    public function clear($channel = '*')
    {
        if ('*' == $channel) {
            $channel = array_keys($this->drivers);
        }
        $this->channel($channel)->clear();
        return $this;
    }

    /**
     * 关闭本次请求日志写入
     */
    public function close($channel = '*')
    {
        if ('*' == $channel) {
            $channel = array_keys($this->drivers);
        }
        $this->channel($channel)->close();
        return $this;
    }

    /**
     * 获取日志信息
     */
    public function getLog($channel = null)
    {
        return $this->channel($channel)->getLog();
    }

    /**
     * 保存日志信息
     */
    public function save()
    {
        /** @var Channel $channel */
        foreach ($this->drivers as $channel) {
            $channel->save();
        }
        return true;
    }

    /**
     * 实时写入日志信息
     */
    public function write($msg, $type = 'info', array $context = [])
    {
        return $this->record($msg, $type, $context, false);
    }

    /**
     * 记录日志信息
     */
    public function log($level, $message, array $context = [])
    {
        $this->record($message, $level, $context);
    }

    /**
     * 记录emergency信息
     */
    public function emergency($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * 记录警报信息
     */
    public function alert($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * 记录紧急情况
     */
    public function critical($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * 记录错误信息
     */
    public function error($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * 记录warning信息
     */
    public function warning($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * 记录notice信息
     */
    public function notice($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * 记录一般信息
     */
    public function info($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * 记录调试信息
     */
    public function debug($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    /**
     * 记录sql信息
     */
    public function sql($message, array $context = [])
    {
        $this->log(__FUNCTION__, $message, $context);
    }

    public function __call($method, $parameters)
    {
        $this->log($method, ...$parameters);
    }
}